package de.doegel.common;

import greendroid.widget.ActionBarItem;
import greendroid.widget.ActionBarItem.Type;
import greendroid.widget.LoaderActionBarItem;

import java.sql.SQLException;
import java.util.List;
import java.util.Vector;

import android.os.AsyncTask;
import android.os.Bundle;
import android.text.Html;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.markupartist.android.widget.PullToRefreshListView;
import com.markupartist.android.widget.PullToRefreshListView.OnRefreshListener;

import de.doegel.common.model.News;
import de.doegel.common.ormlite.OrmLiteGDActivity;
import de.doegel.common.util.ImageDownloader;
import de.doegel.common.util.TextAndProgressBarUtils;
import de.doegel.common.util.Utils;

public class NewsActivity<H extends AbstractDatabaseHelper> extends OrmLiteGDActivity<H> {
	private ImageDownloader imageDownloader = new ImageDownloader();

	class NewsAdapter extends BaseAdapter {
		List<News> all;

		public NewsAdapter(List<News> all) {
			this.all = all;
		}

		public int getCount() {
			return all.size();
		}

		public News getItem(int position) {
			return all.get(position);
		}

		public long getItemId(int position) {
			return position;
		}

		public List<News> getNews() {
			return all;
		}

		private SpannableStringBuilder getHtmlString(News news) {

			SpannableStringBuilder htmlBuilder = new SpannableStringBuilder();

			if (news == null) {
				return htmlBuilder;
			}

			int type = Integer.valueOf(news.type);
			String[] refIdArray = news.refIds.split(",,");
			int refCount = refIdArray.length;
			{
				String str = "<u>" + news.contactName + "</u><br/>";
				if (type == 2) {
					htmlBuilder.append(Utils.makeClickable(NewsActivity.this, str, Utils.createAnimalIntent(NewsActivity.this, Integer.valueOf(news.contactId), null, null, null)));
				} else {
					htmlBuilder.append(Utils.makeClickable(NewsActivity.this, str, Utils.createPersonIntent(NewsActivity.this, Integer.valueOf(news.contactId), null)));
				}
			}

			String startText = "";
			String endText = "";
			boolean underlinable = true;
			switch (type) {
			case 0: {
				if (refCount == 1) {
					startText = getString(R.string.news_type_0);
					endText = getString(R.string.news_type_0_end);
				} else {
					startText = getString(R.string.news_type_0_plural);
					endText = getString(R.string.news_type_0_end_plural);
				}
				break;
			}
			case 1: {
				startText = getString(R.string.news_type_1);
				underlinable = false;
				break;
			}
			case 2: {
				startText = getString(R.string.news_type_2);
				endText = getString(R.string.news_type_2_end);
				break;
			}
			case 3: {
				if (refCount == 1) {
					startText = getString(R.string.news_type_3);
					endText = getString(R.string.news_type_3_end);
				} else {
					startText = getString(R.string.news_type_3_plural);
					endText = getString(R.string.news_type_3_end_plural);
				}
				break;
			}
			case 4: {
				startText = getString(R.string.news_type_4);
				underlinable = false;
				break;
			}
			case 5: {
				startText = getString(R.string.news_type_5);
				underlinable = false;
				break;
			}
			case 6: {
				startText = getString(R.string.news_type_6);
				underlinable = false;
				break;
			}
			case 7: {
				if (refCount == 1) {
					startText = getString(R.string.news_type_7);
					endText = getString(R.string.news_type_7_end);
				} else {
					startText = getString(R.string.news_type_7_plural);
					endText = getString(R.string.news_type_7_end_plural);
				}
				break;
			}
			case 8: {
				if (refCount == 1) {
					startText = getString(R.string.news_type_8);
					endText = getString(R.string.news_type_8_end);
				} else {
					startText = getString(R.string.news_type_8_plural);
					endText = getString(R.string.news_type_8_end_plural);
				}
				break;
			}
			case 10: {
				startText = getString(R.string.news_type_10);
				underlinable = false;
				break;
			}
			default:
				underlinable = false;
				break;
			}
			htmlBuilder.append(Html.fromHtml(startText));
			if (underlinable) {
				htmlBuilder.append(Html.fromHtml("<br/>"));
				String[] nameArray = news.refNames.split(",,");
				if (refCount > 0 && nameArray.length > 0) {
					for (int i = 0; i < nameArray.length; i++) {
						if (refCount >= i) {
							String str = "<u>" + nameArray[i] + "</u><br/>";
							if (type == 0) {
								htmlBuilder.append(Utils.makeClickable(NewsActivity.this, str, Utils.createPersonIntent(NewsActivity.this, Integer.valueOf(refIdArray[i]), null)));
							} else if (type == 3) {
								htmlBuilder.append(Utils.makeClickable(NewsActivity.this, str, Utils.createBreedIntent(NewsActivity.this, Integer.valueOf(refIdArray[i]))));
							} else {
								htmlBuilder.append(Utils.makeClickable(NewsActivity.this, str, Utils.createAnimalIntent(NewsActivity.this, Integer.valueOf(refIdArray[i]), null, null, null)));
							}
						}
					}
				}
				if (!TextUtils.isEmpty(endText)) {
					htmlBuilder.append(endText);
				}
			}
			return htmlBuilder;

		}

		public final View getView(int position, View convertView, ViewGroup parent) {
			View res = convertView;
			if (res == null)
				res = getLayoutInflater().inflate(R.layout.news_item, null);

			TextView newsTextView = (TextView) res.findViewById(R.id.news_text);
			ImageView contactImage = (ImageView) res.findViewById(R.id.contact_image);
			TextView timeTextView = (TextView) res.findViewById(R.id.news_time);

			News news = getItem(position);

			newsTextView.setMovementMethod(LinkMovementMethod.getInstance());
			newsTextView.setText(getHtmlString(news));
			timeTextView.setText(Utils.parseAndFormatNewsDate(NewsActivity.this, IDoegelConstants.MESSAGE_DATE_PARSER_FORMAT, news.timestamp));

			contactImage.setImageResource(R.drawable.empty_contact_image);
			imageDownloader.download(news.imageURL, contactImage);

			return res;
		}
	}

	private LoaderActionBarItem refreshItem = null;
	private NewsAdapter adapter;
	private PullToRefreshListView listview;
	private View textandprogressbar = null;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setActionBarContentView(R.layout.news);
		setTitle(R.string.news_activity_title);
		refreshItem = (LoaderActionBarItem) addActionBarItem(Type.Refresh, R.id.action_bar_refresh);

		listview = (PullToRefreshListView) findViewById(R.id.list);
		listview.setOnRefreshListener(new OnRefreshListener() {
			public void onRefresh() {
				refreshNews();
			}
		});

		textandprogressbar = getLayoutInflater().inflate(R.layout.text_and_progressbar, listview, false);
		listview.addFooterView(textandprogressbar, null, false);
		TextAndProgressBarUtils.initializeTextAndProgressBar(listview, textandprogressbar);

		adapter = new NewsAdapter(new Vector<News>());
		listview.setAdapter(adapter);
		((ProgressBar) listview.findViewById(R.id.pull_to_refresh_progress)).setIndeterminateDrawable(getResources().getDrawable(R.drawable.progressbar_animation));
		if(Utils.isFirstStart(NewsActivity.this)) {
			refreshNews();
		}
		else {
			new FetchNewsFromDBTask().execute();
		}
	}

	@Override
	public boolean onHandleActionBarItemClick(ActionBarItem item, int position) {
		if (item.getItemId() == R.id.action_bar_refresh) {
			refreshNews();
			return true;
		} else {
			return super.onHandleActionBarItemClick(item, position);
		}
	}

	public void refreshNews() {
		new FetchNewsTask().execute(true);
	}

	public void onTextAndProgressBarClick(View view) {
		TextAndProgressBarUtils.configureTextAndProgressBar(listview, null, false, true);
		TextAndProgressBarUtils.showTextAndProgressBar(listview);
		new FetchNewsTask().execute(false);
	}	

	private class FetchNewsFromDBTask extends AsyncTask<Void, Void, List<News>> {
		@Override
		protected List<News> doInBackground(Void... params) {
			List<News> newsList = null;
			try {
				newsList = getHelper().getNewsDao().queryForAll();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			return newsList;
		}

		@Override
		protected void onPostExecute(List<News> result) {
			if (result != null) {
				adapter.getNews().addAll(result);
				listview.onRefreshComplete();
			}
			if (result == null || result.size() == 0) {
				TextAndProgressBarUtils.configureTextAndProgressBar(listview, getString(R.string.news_nothing), false, false);
			} else if (result != null && result.size() > 10){
				TextAndProgressBarUtils.configureTextAndProgressBar(listview, getString(R.string.news_old), false, false);
			} else {
				TextAndProgressBarUtils.configureTextAndProgressBar(listview, "", false, false);
			}

			super.onPostExecute(result);
		}
	}

	private class FetchNewsTask extends AsyncTask<Boolean, Void, List<News>> {
		private int resultSize = 0;
		private boolean newRefresh = false;
		
		@Override
		protected void onPreExecute() {

		}

		@Override
		protected List<News> doInBackground(Boolean... params) {
			newRefresh = params[0];
			List<News> result = ((DoegelApplication) getApplication()).getHttpConnector().fetchNews(NewsActivity.this, newRefresh ? 0 : adapter.getNews().size());
			if (result == null)
				return null;
			resultSize = result.size();
			List<News> news = null;
			try {
				if (newRefresh) {
					getHelper().getNewsDao().delete(getHelper().getNewsDao().queryForAll());					
				}
				for (int i = 0; i < result.size(); i++) {
					getHelper().getNewsDao().create(result.get(i));
				}
				news = getHelper().getNewsDao().queryForAll();
				if (news == null) {
					news = new Vector<News>();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
			return news;
		}

		@Override
		protected void onPostExecute(List<News> news) {
			if (news != null) {
				adapter.getNews().clear();
				adapter.getNews().addAll(news);
				
				if (resultSize < 25) {
					TextAndProgressBarUtils.configureTextAndProgressBar(listview, getString(R.string.news_nomore), false, false);
				} else {
					TextAndProgressBarUtils.configureTextAndProgressBar(listview, getString(R.string.news_more), true, false);
				}
			} else {
				TextAndProgressBarUtils.configureTextAndProgressBar(listview, getString(R.string.network_problem), false, false);
			}
	
			// Call onRefreshComplete when the list has been refreshed.
			if (newRefresh) {
				listview.onRefreshComplete();
				//listview.setLastUpdated("10 days ago");
			} else {
				listview.invalidateViews();
			}
			refreshItem.setLoading(false);

			super.onPostExecute(news);
		}
	}
	
	private static final int CONTEXT_MENU_HOME = 0;
	private static final int CONTEXT_MENU_SETTINGS = 1;
	private static final int CONTEXT_MENU_REFRESH = 2;
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		menu.add(0, CONTEXT_MENU_HOME, 0, R.string.home_context_menu);
		menu.add(0, CONTEXT_MENU_SETTINGS, 0, R.string.settings_context_menu);
		menu.add(0, CONTEXT_MENU_REFRESH, 0, R.string.refresh_context_menu);
		return super.onCreateOptionsMenu(menu);
	}

	@Override
	public boolean onPrepareOptionsMenu(Menu menu) {
		return super.onPrepareOptionsMenu(menu);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case CONTEXT_MENU_HOME:
			startActivity(Utils.createHomeIntent(this));
			return true;
		case CONTEXT_MENU_SETTINGS:
			startActivity(Utils.createSettingsIntent(this));
			finish();
			return true;
		case CONTEXT_MENU_REFRESH:
			refreshItem.setLoading(true);
			refreshNews();
			return true;
		default:
			return super.onOptionsItemSelected(item);
		}
	}
}